package com.nightpiter.controller.reflection;

import java.util.ArrayList;

import android.dalvik.DexFile;

import com.nightpiter.controller.log.Logger;

/**
 * @author Eldar Abusalimov (eldar.abusalimov@gmail.com)
 */
public class Module {

	/** pack that this module belongs to */
	private Pack pack;

	/** name of the module */
	private String name;

	/** prefix of class names (e.g. package name) */
	private String prefix;

	/** necessary classes to load */
	private ArrayList<String> classNames;

	/** class to instantiate */
	private String mainClassName;

	/** authors of the package */
	private ArrayList<String> authors;

	/**
	 * package protected constructor
	 * 
	 * @param pack
	 * @param name
	 * @param prefix
	 * @param classNames
	 * @param mainClassName
	 * @param authors
	 */
	Module(Pack pack, String name, String prefix, ArrayList<String> classNames,
			String mainClassName, ArrayList<String> authors) {
		this.pack = pack;
		pack.addModule(this);
		this.name = name;
		this.prefix = prefix;
		this.classNames = classNames;
		this.mainClassName = mainClassName;
		this.authors = authors;
	}

	/**
	 * load all necessary classes
	 * 
	 * @return the class to be instantiated
	 */
	@SuppressWarnings("unchecked")
	public Class load() {
		final char DOT = '.';
		final char SLASH = '/';
		String prefix = (this.prefix.equals("")) ? "" : this.prefix + SLASH;

		DexFile dexFile = pack.getDexFile();
		Class clazz = null;
		Class extractedClass;
		ClassLoader classLoader = pack.getContext().getClassLoader();
		Logger.log("classLoader: " + classLoader.getClass().getName());
		for (String className : this.classNames) {
			name = (prefix + className).replace(DOT, SLASH);
			classLoader.clearAssertionStatus();
			extractedClass = dexFile.loadClass(name, classLoader);
			if (className == this.mainClassName) {
				clazz = extractedClass;
			}
			if (extractedClass == null) {
				Logger.log("failed to extract: " + name);
			} else {
				Logger.log("extracted class:   " + extractedClass.getName());
			}
		}
		return clazz;
	}

	/**
	 * @return the name
	 */
	public String getName() {
		return name;
	}

	/**
	 * @return the prefix
	 */
	public String getPrefix() {
		return prefix;
	}

	/**
	 * @return the classNames
	 */
	public ArrayList<String> getClassNames() {
		return classNames;
	}

	/**
	 * @return the mainClassName
	 */
	public String getMainClassName() {
		return mainClassName;
	}

	/**
	 * @return the authors
	 */
	public ArrayList<String> getAuthors() {
		return authors;
	}

}
